// ---------------------------------------------------------------------
//
// -- 通用工具函数库
// -- author £
//
// ---------------------------------------------------------------------

const R_62_ARR = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
    'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
    'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
    'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
    'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'
];

let CommonUtil = {
    /** 异步调用 */
    async: function (node, handler, scope, data) {
        this.delay(node, 0.01, handler, scope, data);
    },

    /** 延迟调用 */
    delay: function (node, delay, handler, scope, data) {
        node.runAction(
            cc.sequence(
                cc.delayTime(delay),
                cc.callFunc(handler, scope, data)
            )
        );
    },

    /** 拷贝对象属性 */
    copyProp: function (src, target, excludes) {
        if (excludes === null || excludes === undefined)
            excludes = [];

        for (let prop in src) {
            if (excludes.indexOf(prop) >= 0) {
                continue;
            }

            target[prop] = src[prop];
        }
    },

    /** super方法 */
    mysuper: function (superClass, this_, superFunc, ...args) {
        superClass.prototype[superFunc].call(this_, ...args);
    },

    /** 从节点中取得某个节点的某个组件 */
    getComponent: function (node, subName, compClass) {
        return node.getChildByName(subName).getComponent(compClass);
    },

    /** 补0方法 */
    zeroFix: function (num, fixLen) {
        var numStr = num + "",
            numLen = numStr.length,
            delta = fixLen - numLen;

        for (var i = 0; i < delta; ++i) {
            numStr = "0" + numStr;
        }

        return numStr;
    },

    /** 获取随机数组 */
    getRandomArr: function (origin, num, len) {
        let i = 0, tmp, pos, result = [];

        if (!origin) {
            origin = [];

            for (i = 0; i < len; ++i) {
                origin[origin.length] = i;
            }
        }

        tmp = origin.concat();

        for (i = 0; i < num; ++i) {
            pos = require('MathUtil').getIntRandom(0, tmp.length - 1);
            result[result.length] = tmp[pos];
            tmp.splice(pos, 1);
        }

        return result;
    },

    /** 是否同IP */
    sameIP: function (ip1, ip2) {
        return ip1.substring(0, ip1.lastIndexOf('.')) ===
            ip2.substring(0, ip2.lastIndexOf('.'));
    },

    /** 10进制转n进制（n > 36） */
    toString: function (num, radix, fixLen) {
        let result = '';

        while (num >= radix) {
            result = R_62_ARR[num % radix] + result;
            num = Math.floor(num / radix);
        }

        result = R_62_ARR[num] + result;

        if (fixLen)
            result = this.zeroFix(result, fixLen);

        return result;
    },

    /** n进制转10进制 (n > 36) */
    parseInt: function (str, radix) {
        let result = 0,
            len = str.length,
            char;

        for (let i = 0; i < len; ++i) {
            char = str.charAt(i);

            if (char === '0')
                continue;

            result += Math.pow(radix, len - 1 - i) * R_62_ARR.indexOf(char);
        }

        return result;
    },

    /*
    * Generate a random uuid.
    *
    * USAGE: Math.uuid(length, radix)
    *   length - the desired number of characters
    *   radix  - the number of allowable values for each character.
    *
    * EXAMPLES:
    *   // No arguments  - returns RFC4122, version 4 ID
    *   >>> Math.uuid()
    *   "92329D39-6F5C-4520-ABFC-AAB64544E172"
    *
    *   // One argument - returns ID of the specified length
    *   >>> Math.uuid(15)     // 15 character ID (default base=62)
    *   "VcydxgltxrVZSTV"
    *
    *   // Two arguments - returns ID of the specified length, and radix. (Radix must be <= 62)
    *   >>> Math.uuid(8, 2)  // 8 character ID (base=2)
    *   "01001010"
    *   >>> Math.uuid(8, 10) // 8 character ID (base=10)
    *   "47473046"
    *   >>> Math.uuid(8, 16) // 8 character ID (base=16)
    *   "098F4D35"
    */
    uuid: function (len, radix) {
        let chars = R_62_ARR, uuid = [], i;

        radix = radix || chars.length;

        if (len) {
            // Compact form
            for (i = 0; i < len; i++)
                uuid[i] = chars[0 | Math.random() * radix];
        } else {
            // rfc4122, version 4 form
            let r;

            // rfc4122 requires these characters
            uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-';
            uuid[14] = '4';

            // Fill in random data.  At i==19 set the high bits of clock sequence as
            // per rfc4122, sec. 4.1.5
            for (i = 0; i < 36; i++) {
                if (!uuid[i]) {
                    r = 0 | Math.random() * 16;
                    uuid[i] = chars[(i == 19) ? (r & 0x3) | 0x8 : r];
                }
            }
        }

        return uuid.join('');
    },

    /** 设置苹果权限 */
    setPermission: function () {
        jsb.reflection.callStaticMethod("CommonUtil", "setPermission");
    },

    /** 版本比较 */
    compareVersion: function (versionA, versionB) {
        let vA = versionA.split('.');
        let vB = versionB.split('.');

        for (let i = 0; i < vA.length; ++i) {
            let a = parseInt(vA[i]);
            let b = parseInt(vB[i] || 0);
            if (a === b) {
                continue;
            }
            else {
                return a - b;
            }
        }
        if (vB.length > vA.length) {
            return -1;
        }
        else {
            return 0;
        }
    },

    /** cjson转换 */
    cJson: function (vecstr) {
        return JSON.parse(vecstr.str.replace(/\\\"/g, /\"/));
    },

    /** 上个 */
    pre: function (cur, total, delta) {
        if (delta === undefined || delta === null)
            delta = 1;

        return (cur - delta + total) % total;
    },

    /** 上个 */
    pre: function (cur, total, delta) {
        if (delta === undefined || delta === null)
            delta = 1;

        return (cur + delta + total) % total;
    },

    /** 重置对象池 */
    resetPool: function (pool, parent) {
        let c;

        while (parent.childrenCount) {
            c = parent.children[parent.children.length - 1];
            c.stopAllActions();
            parent.removeChild(c);
            pool.put(c);
        }
    },

    createXHR: function (xhrRef, method, url, ansyc,
        paramstr, cb, onerror, ontimeout,
        timeout) {
        let xhr, timeo = timeout;

        if (xhrRef)
            xhrRef.abort();

        if (!timeout) timeo = 5000;

        xhr = cc.loader.getXMLHttpRequest();

        if (onerror) xhr.onerror = onerror;
        if (ontimeout) xhr.ontimeout = ontimeout;
        if (!ontimeout && onerror) this.ontimeout = onerror;

        console.log('xhr paramstr: ' + paramstr);
        xhr.open(method,
            method === 'GET' ? (url + '?' + paramstr) : url,
            ansyc);
        xhr.onreadystatechange = function () {
            if (xhr.readyState === 4 &&
                (xhr.status >= 200 && xhr.status < 300)) {
                console.log('xhr result:' + url, xhr);

                let xhrData = null;

                try {
                    xhrData = JSON.parse(xhr.responseText);
                } catch (error) {
                    console.log('xhr JSON parse error');
                }

                console.log('parse reuslt:', xhrData);

                if (!xhrData) {
                    console.log('raw result txt:', xhr.responseText);
                }

                if (cb) {
                    cb(xhrData, xhr.responseText);
                }
            } else if (xhr.readyState === 4 && onerror) {
                onerror(xhr.status);
            }
        };

        xhr.timeout = timeo;
        xhr.send(
            method === 'POST' ? paramstr : null
        );

        return xhr;
    },

    sortRank: function (data, scoreKey) {
        let curScore = 0, curRank = 0, lastRank = 0,
            i, len = data.length, player, selfIndex = -1,
            sk = scoreKey || 'score';

        for (i = 0; i < len; ++i) {
            player = data[i];

            if (i === 0) {
                curScore = player[sk];
                curRank = 1;
                lastRank = 1;
                player.rank = 1;
            } else {
                ++curRank;

                if (player[sk] !== curScore)
                    lastRank = curRank;

                player.rank = lastRank;
                curScore = player[sk];
            }
        }
    },

    sign: function (obj) {
        let sdic = Object.keys(obj).sort(),
            result = '', i = 0,
            GameConfig = require('GameConfig');

        for (let ki in sdic) {
            result += (i++ === 0 ? '' : '&') + sdic[ki] + '=' + obj[sdic[ki]];
        }

        console.log('sign result0:', result);
        result += '|' + GameConfig.clientSecret;
        console.log('sign result1:', result);
        result = require('MyCrypt').md5(result);
        console.log('sign result:' + result);
        return result;
    },
};

module.exports = CommonUtil;